package com.ssm.changeunit.command;

import com.ssm.changeunit.*;
import com.ssm.changeunit.diff.*;
import com.ssm.changeunit.persistance.DatabaseManager;
import com.ssm.changeunit.persistance.ManagedChangeUnitDAO;
import com.ssm.changeunit.persistance.ManagedChangeUnitDTO;
import com.ssm.changeunit.persistance.PersistanceException;
import com.ssm.changeunit.util.FileUtil;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import org.apache.log4j.Logger;

/**
 * StatusCommandWorker
 * 
 * 로컬과 가장 최근의 ChangeUnit과의 비교
 * 
 * @author 시리우스
 */
public class StatusCommandWorker extends CommandWorker {

    private Logger log = Logger.getLogger(StatusCommandWorker.class);

    public StatusCommandWorker() {
    }

    public void work(CommandWorkerOptions commandWorkerOptions) throws CommandWorkerException {
        try {
            if (!DatabaseManager.getInstance().isExists()) {
                throw new CommandWorkerException("데이터베이스가 존재하지 않습니다.");
            }
            
            ManagedChangeUnitDAO managedChangeUnitDAO = new ManagedChangeUnitDAO();

            ManagedChangeUnitDTO managedChangeUnitDTO = managedChangeUnitDAO.find();

            ChangeUnit currentChangeUnit = new ChangeUnitFactory().createProduct(managedChangeUnitDTO.getManagedChangeUnitId());

            List<ChangeUnitItem> changeUnitItems = currentChangeUnit.getChangeUnitItems();

            Queue<File> dirQueue = new LinkedList<File>();

            File rootDir = new File(Environment.ROOT_DIR);

            dirQueue.add(rootDir);

            while (!dirQueue.isEmpty()) {
                File dir = dirQueue.poll();

                for (File file : dir.listFiles()) {
                    if (file.isDirectory()) {
                        if (!file.getName().equals(".changeunit")) {
                            dirQueue.add(file);
                        }
                    } else {
                        String relativeFilePath = FileUtil.getRelativePath(file, rootDir);

                        ChangeUnitItem matchChangeUnitItem = null;

                        // ChangeUnit이 있는지 검사한다.
                        for (ChangeUnitItem changeUnitItem : changeUnitItems) {
                            if (changeUnitItem.getFilePath().equals(relativeFilePath)) {
                                matchChangeUnitItem = changeUnitItem;

                                break;
                            }
                        }

                        if (matchChangeUnitItem == null) {
                            log.info("[관리되지 않는 파일 입니다] File: " + file.getAbsolutePath());
                        } else {
                            String destContent = FileUtil.readFromFile(file.getAbsolutePath());

                            String originContent = new String(matchChangeUnitItem.getRefChangeLog().getContent());

                            // 비교
                            List diffs =
                                    new Diff(
                                    originContent.split("\n"),
                                    destContent.split("\n")).diff();

                            if (diffs.size() != 0) {
                                log.info("[수정되었습니다] File: " + file.getName());

                            /*Iterator it = diffs.iterator();
                            
                            while (it.hasNext()) {
                            Difference diff     = (Difference)it.next();
                            int        delStart = diff.getDeletedStart();
                            int        delEnd   = diff.getDeletedEnd();
                            int        addStart = diff.getAddedStart();
                            int        addEnd   = diff.getAddedEnd();
                            String     type     = delEnd != Difference.NONE && addEnd != Difference.NONE ? "change" : (delEnd == Difference.NONE ? "add" : "delete");
                            
                            // 추가된 경우
                            if(type.equals("add")) {
                            log.info("Dest에 추가되었습니다.");
                            log.info("addStart: " + addStart + " addEnd: " + addEnd);
                            }
                            // 삭제된 경우
                            else if(type.equals("delete")) {
                            log.info("Dest에 삭제되었습니다.");
                            log.info("delStart: " + delStart + " delEnd: " + delEnd);
                            }
                            // 변경된 경우
                            else if(type.equals("change")) {
                            log.debug("Change. addStart: " + addStart + " addEnd: " + addEnd + " delStart: " + delStart + " delEnd: " + delEnd);
                            }
                            }*/
                            }
                        }
                    }
                }
            }
        } 
        catch(IOException ex) {
            throw new CommandWorkerException(ex);
        }
        catch (CreateException ex) {
            throw new CommandWorkerException(ex);
        }
        catch (PersistanceException ex) {
            throw new CommandWorkerException(ex);
        }
    }
}